pub mod application;
pub mod assistant;
pub mod authorization;
mod class;
mod class_attribute;
mod class_relation;
mod class_traits;
mod datasource;
mod datasource_class_attribute_mapping;
mod datasource_class_mapping;
mod datasource_class_relation_mapping;
mod domain;
mod domain_dependency;
mod namespace;
mod namespace_classes;
mod relation;
pub mod scheduler;
pub mod system;
pub mod tool;
mod traits;
pub mod workflow;
pub mod workspace;

pub use class::*;
pub use class_attribute::*;
pub use class_relation::*;
pub use class_traits::*;
pub use datasource::*;
pub use datasource_class_attribute_mapping::*;
pub use datasource_class_mapping::*;
pub use datasource_class_relation_mapping::*;
pub use domain::*;
pub use domain_dependency::*;
pub use namespace::*;
pub use namespace_classes::*;
pub use relation::*;
pub use traits::*;

use super::{ValueSize, ValueType};

use serde::{Deserialize, Serialize};

#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)]
pub enum StorageStatus {
    /// WX_WEBSITE
    #[default]
    #[serde(rename = "0")]
    Init = 0,
    /// WX_MINIPROG
    #[serde(rename = "1")]
    Normal = 1,
    /// Deleted
    #[serde(rename = "3")]
    Deleted = 3,
}

pub trait ClassGetter {
    fn get_name() -> anyhow::Result<String> {
        Err(anyhow::anyhow!(""))
    }
    fn get_identifier() -> anyhow::Result<String>;
    fn get_class() -> anyhow::Result<Class>;
}

pub fn common_attributes() -> anyhow::Result<Vec<ClassAttribute>> {
    let attribute_builder = ClassAttributeBuilder::default();

    common_attributes_with_builder(&attribute_builder)
}

pub fn simple_attributes_with_builder(
    builder: &ClassAttributeBuilder,
) -> anyhow::Result<Vec<ClassAttribute>> {
    Ok(vec![
        builder
            .clone()
            .name("id")
            .title("ID")
            .position(0)
            .is_autoincrement(true)
            .data_type(ValueType::Number)
            .build()?,
        builder
            .clone()
            .name("created_at")
            .title("创建时间")
            .position(993)
            .data_type(ValueType::Timestamp)
            .default_value("CURRENT_TIMESTAMP")
            .build()?,
        builder
            .clone()
            .name("updated_at")
            .title("更新时间")
            .position(994)
            .data_type(ValueType::Timestamp)
            .default_value("CURRENT_TIMESTAMP")
            .build()?,
    ])
}

pub fn common_attributes_with_builder(
    builder: &ClassAttributeBuilder,
) -> anyhow::Result<Vec<ClassAttribute>> {
    Ok(vec![
        builder
            .clone()
            .name("id")
            .title("ID")
            .position(0)
            .is_autoincrement(true)
            .data_type(ValueType::Number)
            .build()?,
        builder
            .clone()
            .name("identifier")
            .title("标识")
            .position(0)
            .data_type(ValueType::String)
            .build()?,
        builder
            .clone()
            .name("name")
            .title("名称")
            .position(1)
            .data_type(ValueType::String)
            .build()?,
        builder
            .clone()
            .name("title")
            .title("标题")
            .position(2)
            .data_type(ValueType::String)
            .build()?,
        builder
            .clone()
            .name("icon")
            .title("图标")
            .position(3)
            .data_type(ValueType::String)
            .build()?,
        builder
            .clone()
            .name("description")
            .title("描述")
            .position(991)
            .default_value(String::from(""))
            .data_type(ValueType::String)
            .value_size(ValueSize::Normal)
            .build()?,
        builder
            .clone()
            .name("options")
            .title("选项")
            .position(992)
            .default_value(String::from("{}"))
            .data_type(ValueType::String)
            .build()?,
        builder
            .clone()
            .name("created_at")
            .title("创建时间")
            .position(993)
            .data_type(ValueType::Timestamp)
            .default_value("CURRENT_TIMESTAMP")
            .build()?,
        builder
            .clone()
            .name("updated_at")
            .title("更新时间")
            .position(994)
            .data_type(ValueType::Timestamp)
            .default_value("CURRENT_TIMESTAMP")
            .build()?,
    ])
}

#[macro_export]
macro_rules! impl_from_value {
    // 模式匹配
    ($class:ident) => {
        impl TryFrom<Value> for $class {
            type Error = anyhow::Error;

            fn try_from(value: Value) -> Result<Self, Self::Error> {
                let class = Self::get_class()?;
                let v: serde_json::Value = class.to_value(&class, &value)?.try_into()?;
                let res = serde_json::from_value(v).map_err(|err| {
                    tracing::debug!("{}", err);
                    anyhow::anyhow!("{}", err)
                })?;
                Ok(res)
            }
        }

        impl TryInto<Value> for $class {
            type Error = anyhow::Error;

            fn try_into(self) -> Result<Value, Self::Error> {
                Ok(serde_json::to_value(self)
                    .map_err(|err| anyhow::anyhow!("{}", err))?
                    .try_into()?)
            }
        }

        impl TryInto<std::collections::HashMap<String, Value>> for $class {
            type Error = anyhow::Error;

            fn try_into(self) -> Result<std::collections::HashMap<String, Value>, Self::Error> {
                let v: Value = self.try_into()?;
                match v {
                    Value::Object(map) => Ok(map),
                    _ => Err(anyhow::anyhow!("数据不合法!")),
                }
            }
        }
    };
}

#[macro_export]
macro_rules! impl_class_persistence_getter {
    // 模式匹配
    ($class:ident, $table_name:expr) => {
        impl ClassPersistenceGetter for $class {
            fn table_name() -> anyhow::Result<String> {
                Ok(String::from($table_name))
            }
            fn class_persistence() -> anyhow::Result<Option<ClassPersistence>> {
                let mut builder = ClassPersistenceBuilder::default();
                let mut attr_persistences: Vec<ClassAttributePersistence> = vec![];
                if let Some(attributes) = Self::get_class()?.attributes {
                    for attribute in attributes {
                        if !attribute.is_persistent {
                            continue;
                        }
                        //
                        attr_persistences.push(ClassAttributePersistence::try_from(attribute)?);
                    }
                } else {
                }
                builder
                    .table_name(Self::table_name()?)
                    .columns(attr_persistences);
                Ok(Some(builder.build()?))
            }
        }
    };
}

#[macro_export]
macro_rules! impl_class_relations_getter {
    // 模式匹配
    ($class:ident, $relations:expr) => {
        impl ClassRelationGetter for $class {
            fn class_relations() -> anyhow::Result<Vec<ClassRelation>> {
                //
                Ok($relations)
            }
        }
    };
}
